Clean up the xenoprofile hypercall interface.
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Wed, 19 Apr 2006 17:43:39 +0000 (18:43 +0100)
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Wed, 19 Apr 2006 17:43:39 +0000 (18:43 +0100)
Signed-off-by: Jose Renato Santos <jsantos@hpl.hp.com>
linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c
linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h
xen/arch/x86/oprofile/xenoprof.c
xen/arch/x86/x86_32/entry.S
xen/arch/x86/x86_64/entry.S
xen/include/public/xenoprof.h

index f5184a2c0c3977472df6d6eea7c2f06a7ba292af..bcfdc23e74d4f3167aa6bd6c129cef68feff7a1d 100644 (file)
@@ -35,8 +35,9 @@ static void xenoprof_stop(void);
 void * vm_map_xen_pages(unsigned long maddr, int vm_size, pgprot_t prot);
 
 static int xenoprof_enabled = 0;
-static int num_events = 0;
+static unsigned int num_events = 0;
 static int is_primary = 0;
+static int active_defined;
 
 /* sample buffers shared with Xen */
 xenoprof_buf_t * xenoprof_buf[MAX_VIRT_CPUS];
@@ -106,7 +107,7 @@ static irqreturn_t
 xenoprof_ovf_interrupt(int irq, void * dev_id, struct pt_regs * regs)
 {
        int head, tail, size;
-       xenoprof_buf_t * buf;
+       struct xenoprof_buf * buf;
        int cpu;
 
        cpu = smp_processor_id();
@@ -196,28 +197,49 @@ static int bind_virq(void)
 static int xenoprof_setup(void)
 {
        int ret;
+       int i;
 
        ret = bind_virq();
        if (ret)
                return ret;
 
        if (is_primary) {
-               ret = HYPERVISOR_xenoprof_op(XENOPROF_reserve_counters,
-                                            (unsigned long)NULL,
-                                            (unsigned long)NULL);
+               struct xenoprof_counter counter;
+
+               /* Define dom0 as an active domain if not done yet */
+               if (!active_defined) {
+                       domid_t domid;
+                       ret = HYPERVISOR_xenoprof_op(XENOPROF_reset_active_list, NULL);
+                       if (ret)
+                               goto err;
+                       domid = 0;
+                       ret = HYPERVISOR_xenoprof_op(XENOPROF_set_active, &domid);
+                       if (ret)
+                               goto err;
+                       active_defined = 1;
+               }
+
+               ret = HYPERVISOR_xenoprof_op(XENOPROF_reserve_counters, NULL);
                if (ret)
                        goto err;
+               for (i=0; i<num_events; i++) {
+                       counter.ind       = i;
+                       counter.count     = (uint64_t)counter_config[i].count;
+                       counter.enabled   = (uint32_t)counter_config[i].enabled;
+                       counter.event     = (uint32_t)counter_config[i].event;
+                       counter.kernel    = (uint32_t)counter_config[i].kernel;
+                       counter.user      = (uint32_t)counter_config[i].user;
+                       counter.unit_mask = (uint64_t)counter_config[i].unit_mask;
+                       HYPERVISOR_xenoprof_op(XENOPROF_counter, 
+                                              &counter);
+               }
+               ret = HYPERVISOR_xenoprof_op(XENOPROF_setup_events, NULL);
 
-               ret = HYPERVISOR_xenoprof_op(XENOPROF_setup_events,
-                                            (unsigned long)&counter_config,
-                                            (unsigned long)num_events);
                if (ret)
                        goto err;
        }
 
-       ret = HYPERVISOR_xenoprof_op(XENOPROF_enable_virq,
-                                    (unsigned long)NULL,
-                                    (unsigned long)NULL);
+       ret = HYPERVISOR_xenoprof_op(XENOPROF_enable_virq, NULL);
        if (ret)
                goto err;
 
@@ -233,17 +255,15 @@ static void xenoprof_shutdown(void)
 {
        xenoprof_enabled = 0;
 
-       HYPERVISOR_xenoprof_op(XENOPROF_disable_virq,
-                              (unsigned long)NULL,
-                              (unsigned long)NULL);
+       HYPERVISOR_xenoprof_op(XENOPROF_disable_virq, NULL);
 
        if (is_primary) {
-               HYPERVISOR_xenoprof_op(XENOPROF_release_counters,
-                                      (unsigned long)NULL,
-                                      (unsigned long)NULL);
+               HYPERVISOR_xenoprof_op(XENOPROF_release_counters, NULL);
+               active_defined = 0;
        }
 
        unbind_virq();
+
 }
 
 
@@ -252,9 +272,8 @@ static int xenoprof_start(void)
        int ret = 0;
 
        if (is_primary)
-               ret = HYPERVISOR_xenoprof_op(XENOPROF_start,
-                                            (unsigned long)NULL,
-                                            (unsigned long)NULL);
+               ret = HYPERVISOR_xenoprof_op(XENOPROF_start, NULL);
+
        return ret;
 }
 
@@ -262,20 +281,43 @@ static int xenoprof_start(void)
 static void xenoprof_stop(void)
 {
        if (is_primary)
-               HYPERVISOR_xenoprof_op(XENOPROF_stop,
-                                      (unsigned long)NULL,
-                                      (unsigned long)NULL);
+               HYPERVISOR_xenoprof_op(XENOPROF_stop, NULL);
 }
 
 
 static int xenoprof_set_active(int * active_domains,
-                         unsigned int adomains)
+                              unsigned int adomains)
 {
        int ret = 0;
-       if (is_primary)
-               ret = HYPERVISOR_xenoprof_op(XENOPROF_set_active,
-                                            (unsigned long)active_domains,
-                                            (unsigned long)adomains);
+       int i;
+       int set_dom0 = 0;
+       domid_t domid;
+
+       if (!is_primary)
+               return 0;
+
+       if (adomains > MAX_OPROF_DOMAINS)
+               return -E2BIG;
+
+       ret = HYPERVISOR_xenoprof_op(XENOPROF_reset_active_list, NULL);
+       if (ret)
+               return ret;
+
+       for (i=0; i<adomains; i++) {
+               domid = active_domains[i];
+               ret = HYPERVISOR_xenoprof_op(XENOPROF_set_active, &domid);
+               if (ret)
+                       return (ret);
+               if (active_domains[i] == 0)
+                       set_dom0 = 1;
+       }
+       /* dom0 must always be active but may not be in the list */ 
+       if (!set_dom0) {
+               domid = 0;
+               ret = HYPERVISOR_xenoprof_op(XENOPROF_set_active, &domid);
+       }
+       
+       active_defined = 1;
        return ret;
 }
 
@@ -325,44 +367,48 @@ static int using_xenoprof;
 
 int __init oprofile_arch_init(struct oprofile_operations * ops)
 {
-       xenoprof_init_result_t result;
-       xenoprof_buf_t * buf;
-       int max_samples = 16;
+       struct xenoprof_init init;
+       struct xenoprof_buf * buf;
        int vm_size;
        int npages;
+       int ret;
        int i;
 
-       int ret = HYPERVISOR_xenoprof_op(XENOPROF_init,
-                                        (unsigned long)max_samples,
-                                        (unsigned long)&result);
+       init.max_samples = 16;
+       ret = HYPERVISOR_xenoprof_op(XENOPROF_init, &init);
 
        if (!ret) {
                pgprot_t prot = __pgprot(_KERNPG_TABLE);
 
-               num_events = result.num_events;
-               is_primary = result.is_primary;
-               nbuf = result.nbuf;
+               num_events = init.num_events;
+               is_primary = init.is_primary;
+               nbuf = init.nbuf;
 
-               npages = (result.bufsize * nbuf - 1) / PAGE_SIZE + 1;
+               /* just in case - make sure we do not overflow event list 
+                   (i.e. counter_config list) */
+               if (num_events > OP_MAX_COUNTER)
+                       num_events = OP_MAX_COUNTER;
+
+               npages = (init.bufsize * nbuf - 1) / PAGE_SIZE + 1;
                vm_size = npages * PAGE_SIZE;
 
-               shared_buffer = (char *) vm_map_xen_pages(result.buf_maddr,
-                                                         vm_size, prot);
+               shared_buffer = (char *)vm_map_xen_pages(init.buf_maddr,
+                                                        vm_size, prot);
                if (!shared_buffer) {
                        ret = -ENOMEM;
                        goto out;
                }
 
                for (i=0; i< nbuf; i++) {
-                       buf = (xenoprof_buf_t*) 
-                               &shared_buffer[i * result.bufsize];
+                       buf = (struct xenoprof_buf*) 
+                               &shared_buffer[i * init.bufsize];
                        BUG_ON(buf->vcpu_id >= MAX_VIRT_CPUS);
                        xenoprof_buf[buf->vcpu_id] = buf;
                }
 
                /*  cpu_type is detected by Xen */
                cpu_type[XENOPROF_CPU_TYPE_SIZE-1] = 0;
-               strncpy(cpu_type, result.cpu_type, XENOPROF_CPU_TYPE_SIZE - 1);
+               strncpy(cpu_type, init.cpu_type, XENOPROF_CPU_TYPE_SIZE - 1);
                xenoprof_ops.cpu_type = cpu_type;
 
                init_driverfs();
@@ -371,6 +417,8 @@ int __init oprofile_arch_init(struct oprofile_operations * ops)
 
                for (i=0; i<NR_CPUS; i++)
                        ovf_irq[i] = -1;
+
+               active_defined = 0;
        }
  out:
        printk(KERN_INFO "oprofile_arch_init: ret %d, events %d, "
@@ -389,7 +437,5 @@ void __exit oprofile_arch_exit(void)
                shared_buffer = NULL;
        }
        if (is_primary)
-               HYPERVISOR_xenoprof_op(XENOPROF_shutdown,
-                                      (unsigned long)NULL,
-                                      (unsigned long)NULL);
+               HYPERVISOR_xenoprof_op(XENOPROF_shutdown, NULL);
 }
index 87e123bf78ed677fd17e3c365695ac4db2f1664b..491362c9769e8e99569dae35a806bfe643db56d8 100644 (file)
@@ -338,9 +338,9 @@ HYPERVISOR_callback_op(
 
 static inline int
 HYPERVISOR_xenoprof_op(
-       int op, unsigned long arg1, unsigned long arg2)
+       int op, void *arg)
 {
-       return _hypercall3(int, xenoprof_op, op, arg1, arg2);
+       return _hypercall2(int, xenoprof_op, op, arg);
 }
 
 
index ecd9abd2cf026b3af577aa506ca938d77d834809..f2070da55bbf84392ee21a7cd2458620c7f1ea74 100644 (file)
@@ -4,6 +4,7 @@
  *            (email: xenoprof@groups.hp.com)
  */
 
+#include <xen/guest_access.h>
 #include <xen/sched.h>
 #include <public/xenoprof.h>
 
@@ -12,7 +13,7 @@
 /* Limit amount of pages used for shared buffer (per domain) */
 #define MAX_OPROF_SHARED_PAGES 32
 
-int active_domains[MAX_OPROF_DOMAINS];
+domid_t active_domains[MAX_OPROF_DOMAINS];
 int active_ready[MAX_OPROF_DOMAINS];
 unsigned int adomains;
 unsigned int activated;
@@ -84,7 +85,8 @@ static void xenoprof_reset_buf(struct domain *d)
 
 int active_index(struct domain *d)
 {
-    int i, id = d->domain_id;
+    int i;
+    domid_t id = d->domain_id;
 
     for ( i = 0; i < adomains; i++ )
         if ( active_domains[i] == id )
@@ -137,13 +139,11 @@ int reset_active(struct domain *d)
     return 0;
 }
 
-int set_active_domains(int num)
+int reset_active_list(void)
 {
-    int primary;
     int i;
     struct domain *d;
 
-    /* Reset any existing active domains from previous runs. */
     for ( i = 0; i < adomains; i++ )
     {
         if ( active_ready[i] )
@@ -157,24 +157,20 @@ int set_active_domains(int num)
         }
     }
 
-    adomains = num;
+    adomains = 0;
+    activated = 0;
 
-    /* Add primary profiler to list of active domains if not there yet */
-    primary = active_index(primary_profiler);
-    if ( primary == -1 )
-    {
-        /* Return if there is no space left on list. */
-        if ( num >= MAX_OPROF_DOMAINS )
-            return -E2BIG;
-        active_domains[num] = primary_profiler->domain_id;
-        num++;
-    }
+    return 0;
+}
 
-    adomains = num;
-    activated = 0;
+int add_active_list (domid_t domid)
+{
+    if ( adomains >= MAX_OPROF_DOMAINS )
+        return -E2BIG;
 
-    for ( i = 0; i < adomains; i++ )
-        active_ready[i] = 0;
+    active_domains[adomains] = domid;
+    active_ready[adomains] = 0;
+    adomains++;
 
     return 0;
 }
@@ -353,26 +349,31 @@ void free_xenoprof_pages(struct domain *d)
     d->xenoprof = NULL;
 }
 
-int xenoprof_init(int max_samples, xenoprof_init_result_t *init_result)
+int xenoprof_op_init(GUEST_HANDLE(void) arg)
 {
-    xenoprof_init_result_t result;
+    struct xenoprof_init xenoprof_init;
     int is_primary, num_events;
     struct domain *d = current->domain;
     int ret;
 
-    ret = nmi_init(&num_events, &is_primary, result.cpu_type);
-    if ( is_primary )
-        primary_profiler = current->domain;
+    if ( copy_from_guest(&xenoprof_init, arg, 1) )
+        return -EFAULT;
 
+    ret = nmi_init(&num_events, 
+                   &is_primary, 
+                   xenoprof_init.cpu_type);
     if ( ret < 0 )
         goto err;
 
+    if ( is_primary )
+        primary_profiler = current->domain;
+
     /*
      * We allocate xenoprof struct and buffers only at first time xenoprof_init
      * is called. Memory is then kept until domain is destroyed.
      */
     if ( (d->xenoprof == NULL) &&
-         ((ret = alloc_xenoprof_struct(d, max_samples)) < 0) )
+         ((ret = alloc_xenoprof_struct(d, xenoprof_init.max_samples)) < 0) )
         goto err;
 
     xenoprof_reset_buf(d);
@@ -381,13 +382,13 @@ int xenoprof_init(int max_samples, xenoprof_init_result_t *init_result)
     d->xenoprof->domain_ready = 0;
     d->xenoprof->is_primary = is_primary;
 
-    result.is_primary = is_primary;
-    result.num_events = num_events;
-    result.nbuf = d->xenoprof->nbuf;
-    result.bufsize = d->xenoprof->bufsize;
-    result.buf_maddr = __pa(d->xenoprof->rawbuf);
+    xenoprof_init.is_primary = is_primary;
+    xenoprof_init.num_events = num_events;
+    xenoprof_init.nbuf = d->xenoprof->nbuf;
+    xenoprof_init.bufsize = d->xenoprof->bufsize;
+    xenoprof_init.buf_maddr = __pa(d->xenoprof->rawbuf);
 
-    if ( copy_to_user((void *)init_result, (void *)&result, sizeof(result)) )
+    if ( copy_to_guest(arg, &xenoprof_init, 1) )
     {
         ret = -EFAULT;
         goto err;
@@ -409,7 +410,7 @@ int xenoprof_init(int max_samples, xenoprof_init_result_t *init_result)
                    || (op == XENOPROF_release_counters) \
                    || (op == XENOPROF_shutdown))
 
-int do_xenoprof_op(int op, unsigned long arg1, unsigned long arg2)
+int do_xenoprof_op(int op, GUEST_HANDLE(void) arg)
 {
     int ret = 0;
 
@@ -423,20 +424,24 @@ int do_xenoprof_op(int op, unsigned long arg1, unsigned long arg2)
     switch ( op )
     {
     case XENOPROF_init:
-        ret = xenoprof_init((int)arg1, (xenoprof_init_result_t *)arg2);
+        ret = xenoprof_op_init(arg);
         break;
 
+    case XENOPROF_reset_active_list:
+    {
+        ret = reset_active_list();
+        break;
+    }
     case XENOPROF_set_active:
+    {
+        domid_t domid;
         if ( xenoprof_state != XENOPROF_IDLE )
             return -EPERM;
-        if ( arg2 > MAX_OPROF_DOMAINS )
-            return -E2BIG;
-        if ( copy_from_user((void *)&active_domains, 
-                            (void *)arg1, arg2*sizeof(int)) )
+        if ( copy_from_guest(&domid, arg, 1) )
             return -EFAULT;
-        ret = set_active_domains(arg2);
+        ret = add_active_list(domid);
         break;
-
+    }
     case XENOPROF_reserve_counters:
         if ( xenoprof_state != XENOPROF_IDLE )
             return -EPERM;
@@ -445,15 +450,34 @@ int do_xenoprof_op(int op, unsigned long arg1, unsigned long arg2)
             xenoprof_state = XENOPROF_COUNTERS_RESERVED;
         break;
 
-    case XENOPROF_setup_events:
+    case XENOPROF_counter:
+    {
+        struct xenoprof_counter counter;
         if ( xenoprof_state != XENOPROF_COUNTERS_RESERVED )
             return -EPERM;
         if ( adomains == 0 )
-            set_active_domains(0);
+            return -EPERM;
 
-        if ( copy_from_user((void *)&counter_config, (void *)arg1, 
-                            arg2 * sizeof(struct op_counter_config)) )
+        if ( copy_from_guest(&counter, arg, 1) )
             return -EFAULT;
+
+        if ( counter.ind > OP_MAX_COUNTER )
+            return -E2BIG;
+
+        counter_config[counter.ind].count     = (unsigned long) counter.count;
+        counter_config[counter.ind].enabled   = (unsigned long) counter.enabled;
+        counter_config[counter.ind].event     = (unsigned long) counter.event;
+        counter_config[counter.ind].kernel    = (unsigned long) counter.kernel;
+        counter_config[counter.ind].user      = (unsigned long) counter.user;
+        counter_config[counter.ind].unit_mask = (unsigned long) counter.unit_mask;
+
+        ret = 0;
+        break;
+    }
+
+    case XENOPROF_setup_events:
+        if ( xenoprof_state != XENOPROF_COUNTERS_RESERVED )
+            return -EPERM;
         ret = nmi_setup_events();
         if ( !ret )
             xenoprof_state = XENOPROF_READY;
@@ -526,3 +550,13 @@ int do_xenoprof_op(int op, unsigned long arg1, unsigned long arg2)
 
     return ret;
 }
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
index 79689d65be32d055b30c2475655d422e117adfb7..1c1cf83901d3911c99ed694da6005542ab5322c4 100644 (file)
@@ -682,7 +682,7 @@ ENTRY(hypercall_args_table)
         .byte 2 /* do_nmi_op            */
         .byte 2 /* do_arch_sched_op     */
         .byte 2 /* do_callback_op       */  /* 30 */
-        .byte 3 /* do_xenoprof_op       */
+        .byte 2 /* do_xenoprof_op       */
         .rept NR_hypercalls-(.-hypercall_args_table)
         .byte 0 /* do_ni_hypercall      */
         .endr
index 266c1c99715bb001e60e7a02f0e248f047706eb7..9c27e2a5950bdcab246c01eac5d6fae8cdfce2c2 100644 (file)
@@ -590,7 +590,7 @@ ENTRY(hypercall_args_table)
         .byte 2 /* do_nmi_op            */
         .byte 2 /* do_arch_sched_op     */
         .byte 2 /* do_callback_op       */  /* 30 */
-        .byte 3 /* do_xenoprof_op       */
+        .byte 2 /* do_xenoprof_op       */
         .rept NR_hypercalls-(.-hypercall_args_table)
         .byte 0 /* do_ni_hypercall      */
         .endr
index 134df887c4bd2e2d9faf4aad762fd3647fbca501..0699834d5dfea917aa10fa58568710bd6e84ab59 100644 (file)
 #define __XEN_PUBLIC_XENOPROF_H__
 
 /*
- * Commands to HYPERVISOR_pmc_op().
+ * Commands to HYPERVISOR_xenoprof_op().
  */
-#define XENOPROF_init               0
-#define XENOPROF_set_active         1
-#define XENOPROF_reserve_counters   3
-#define XENOPROF_setup_events       4
-#define XENOPROF_enable_virq        5
-#define XENOPROF_start              6
-#define XENOPROF_stop               7
-#define XENOPROF_disable_virq       8
-#define XENOPROF_release_counters   9
-#define XENOPROF_shutdown          10
+#define XENOPROF_init                0
+#define XENOPROF_reset_active_list   1
+#define XENOPROF_reset_passive_list  2
+#define XENOPROF_set_active          3
+#define XENOPROF_set_passive         4
+#define XENOPROF_reserve_counters    5
+#define XENOPROF_counter             6
+#define XENOPROF_setup_events        7
+#define XENOPROF_enable_virq         8
+#define XENOPROF_start               9
+#define XENOPROF_stop               10
+#define XENOPROF_disable_virq       11
+#define XENOPROF_release_counters   12
+#define XENOPROF_shutdown           13
 
 #define MAX_OPROF_EVENTS    32
 #define MAX_OPROF_DOMAINS   25 
@@ -50,25 +54,29 @@ typedef struct xenoprof_buf {
 } xenoprof_buf_t;
 DEFINE_GUEST_HANDLE(xenoprof_buf_t);
 
-typedef struct xenoprof_init_result {
+typedef struct xenoprof_init {
+    int32_t  max_samples;
     int32_t  num_events;
     int32_t  is_primary;
     int32_t  nbuf;
     int32_t  bufsize;
     uint64_t buf_maddr;
     char cpu_type[XENOPROF_CPU_TYPE_SIZE];
-} xenoprof_init_result_t;
-DEFINE_GUEST_HANDLE(xenoprof_init_result_t);
+} xenoprof_init_t;
+DEFINE_GUEST_HANDLE(xenoprof_init_t);
+
+typedef struct xenoprof_counter {
+    uint32_t ind;
+    uint64_t count;
+    uint32_t enabled;
+    uint32_t event;
+    uint32_t hypervisor;
+    uint32_t kernel;
+    uint32_t user;
+    uint64_t unit_mask;
+} xenoprof_counter_t;
+DEFINE_GUEST_HANDLE(xenoprof_counter_t);
 
-typedef struct xenoprof_counter_config {
-    unsigned long count;
-    unsigned long enabled;
-    unsigned long event;
-    unsigned long kernel;
-    unsigned long user;
-    unsigned long unit_mask;
-} xenoprof_counter_config_t;
-DEFINE_GUEST_HANDLE(xenoprof_counter_config_t);
 
 #endif /* __XEN_PUBLIC_XENOPROF_H__ */